package cn.iocoder.ny.module.mall.service.impl;

import cn.iocoder.ny.module.mall.domain.MallConfig;
import cn.iocoder.ny.module.mall.domain.MallOrder;
import cn.iocoder.ny.module.mall.domain.vo.MallWeChatPayVo;
import cn.iocoder.ny.module.mall.service.IMallConfigService;
import cn.iocoder.ny.module.mall.service.IMallOrderService;
import cn.iocoder.ny.module.mall.service.IMallWxPayService;
import cn.iocoder.ny.module.mall.utils.wxpay.IdUtils;
import cn.iocoder.ny.module.mall.utils.wxpay.NotifyUrlUtil;
import cn.iocoder.ny.module.mall.utils.wxpay.ResultModel;
import cn.iocoder.ny.module.mall.utils.wxpay.WxPayUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author lc
 * @date 2024/07/23/ 11:57
 * @description:
 */
@Service
@Slf4j
public class MallWxPayServiceImpl implements IMallWxPayService {
    @Autowired
    IMallConfigService mallConfigService;

    @Autowired
    @Lazy
    IMallOrderService iMallOrderService;


    @Value("${v2pay.paynotifyurl}")
    private String paynotifyurl;

    @Value("${v2pay.refundnotifyurl}")
    private String refundnotifyurl;

    /**
     * 获取商户小程序配置
     *
     * @param appid
     * @return
     */
    @SneakyThrows
    private MallConfig config(String appid) {
        QueryWrapper<MallConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("appid", appid);
        MallConfig config = mallConfigService.getOne(queryWrapper, false);
        if (config == null) {
            throw new RuntimeException("商户配置不存在");
        }
        //return MallConfigEncryptionUtil.decryptWithAES(config);
        return config;
    }


    @SneakyThrows
    private MallConfig configtl(Long TenantId) {
        QueryWrapper<MallConfig> queryWrapper = new QueryWrapper<>();
        //todo lg
        queryWrapper.eq("tenant_id", TenantId);

        MallConfig config = mallConfigService.getOne(queryWrapper, false);
        if (config == null) {
            throw new RuntimeException("商户配置不存在----lg");
        }
        //return MallConfigEncryptionUtil.decryptWithAES(config);
        return config;
    }

    @Override
    public ResultModel<PrepayWithRequestPaymentResponse> newpay(MallWeChatPayVo vo) {
        MallConfig mallConfig = configtl(vo.getTenantId());
        //DB很又可能换其他


        vo.setAppid(mallConfig.getAppid()); //  String appid = mallConfig.getAppid();
        WxPayUtil wxPayUtil = new WxPayUtil(mallConfig);
        String strOrderNo = String.valueOf(vo.getOrderNo()); //L 转下 string ;
        String yudaoNotifyurl = paynotifyurl + vo.getAppid() + "/" + vo.getOrderNo();




        return wxPayUtil.prepayByJsapi(vo.getDescription(), strOrderNo, vo.getAttach(), vo.getOpenId(), vo.getTotal(), yudaoNotifyurl);
    }


    /**
     * JSAPI下单(小程序支付)
     *
     * @param vo
     * @return
     */
    @Override
    public ResultModel<PrepayWithRequestPaymentResponse> prepayByJsapi(MallWeChatPayVo vo) {
        //生成订单号
        //todo 改成查
        //vo.setOrderNo(IdUtils.getSnowId());  //外面弄好
        //appid需要运算出来。或者控制器登录 拿到;因为notify要用

        // vo.setOrderNo("or"+IdUtils.getSnowId());
        vo.setDescription("订单号：" + vo.getOrderNo());
        log.info("微信支付参数订单号：" + vo.getOrderNo());
        MallConfig mallConfig = configtl(vo.getTenantId());
        vo.setAppid(mallConfig.getAppid()); //  String appid = mallConfig.getAppid();

        WxPayUtil wxPayUtil = new WxPayUtil(mallConfig);
        //String notifyurl = NotifyUrlUtil.getNotifyUrl(vo);
        //String callurl = "https://2rz24qd15207.vicp.fun/api/ordercallback"
        //String yudaoNotifyurl = "https://2rz24qd15207.vicp.fun"+"/v2pay/notify/payNotify/"+vo.getAppid()+"/"+vo.getOrderNo();
        //https://2rz24qd15207.vicp.fun/admin-api/v2pay/postman01  todo post通


        //String yudaoNotifyurl = "https://2rz24qd15207.vicp.fun"+"/admin-api/v2pay/notify/payNotify/"+vo.getAppid()+"/"+vo.getOrderNo();
        String yudaoNotifyurl = paynotifyurl + vo.getAppid() + "/" + vo.getOrderNo();
        log.info("回调地址：{}", yudaoNotifyurl);
        //String yudaoNotifyurl = "https://nysaas.mynatapp.cc"+"/v2pay/notify/payNotify/"+vo.getAppid()+"/"+vo.getOrderNo();;
        String strOrderNo = String.valueOf(vo.getOrderNo()); //L 转下 string ;

        //订单价格 例如 199元 * 数量2件 = 199 * 2 * 100b = 398元
        if (vo.getTotal() == 0) {   //因为是小int
            return null;
        }

        return wxPayUtil.prepayByJsapi(vo.getDescription(), strOrderNo, vo.getAttach(), vo.getOpenId(), vo.getTotal(), yudaoNotifyurl);
    }

    /**
     * 支付通知
     *
     * @param request
     * @param appId
     * @return
     */
    @Override
    public ResultModel<Transaction> notify(HttpServletRequest request, String appId) {
        WxPayUtil wxPayUtil = new WxPayUtil(config(appId));
        return wxPayUtil.notify(request);
    }

    /**
     * 根据订单号查询订单
     *
     * @param vo
     * @return
     */
    @Override
    public ResultModel<Transaction> queryByOutTradeNo(MallWeChatPayVo vo) {
        WxPayUtil wxPayUtil = new WxPayUtil(config(vo.getAppid()));
        String strOrderNo = String.valueOf(vo.getOrderNo()); //L 转下 string ;
        return wxPayUtil.queryByOutTradeNo(strOrderNo);
    }

    /**
     * 微信支付关闭
     *
     * @param vo
     */
    @Override
    public ResultModel<Transaction> closeByOutTradeNo(MallWeChatPayVo vo) {
        WxPayUtil wxPayUtil = new WxPayUtil(config(vo.getAppid()));
        String strOrderNo = Long.toString(vo.getOrderNo());
        return wxPayUtil.closeByOutTradeNo(strOrderNo);
    }

    /**
     * 微信支付退款
     *
     * @param vo
     * @return
     */
    @Override
    public ResultModel<Refund> refundsByOutTradeNo(MallWeChatPayVo vo) {

        vo.setOutRefundNo("refund" + IdUtils.getSnowId());
        WxPayUtil wxPayUtil = new WxPayUtil(configtl(vo.getTenantId()));

        //根据订单号 查询这个订单；为了拿价格
        MallOrder mallOrder = iMallOrderService.getById(vo.getOrderNo()); //订单号

        String strOrderNo = Long.toString(vo.getOrderNo());

        //bigdecimal 转 long
        //BigDecimal roundedTotal = mallOrder.getTotalAmount().setScale(2, RoundingMode.HALF_UP);
        BigDecimal roundedTotal = mallOrder.getTotalAmount();
        BigDecimal wxBig = roundedTotal.multiply(BigDecimal.valueOf(100));
        Long total = wxBig.longValue();
        Long refund = total;


        // String yudaoNotifyurlrefund = "https://2rz24qd15207.vicp.fun"+"/admin-api/v2pay/notify/refundNotify/"+vo.getAppid()+"/"+vo.getOrderNo();
        String yudaoNotifyurlrefund = refundnotifyurl + vo.getAppid() + "/" + vo.getOrderNo();

        return wxPayUtil.refundsByOutTradeNo(strOrderNo, vo.getOutRefundNo(), total, refund, yudaoNotifyurlrefund);
    }

    /**
     * 退款结果通知
     *
     * @param
     */
    @Override
    public ResultModel<RefundNotification> refundNotify(HttpServletRequest request, String appId) {

        WxPayUtil wxPayUtil = new WxPayUtil(config(appId));
        return wxPayUtil.refundNotify(request);
    }

    /**
     * 支付退款查询
     *
     * @param vo
     * @return
     */
    @Override
    public ResultModel<Refund> refundsQueryByOutRefundNo(MallWeChatPayVo vo) {
        WxPayUtil wxPayUtil = new WxPayUtil(config(vo.getAppid()));
        return wxPayUtil.refundsQueryByOutRefundNo(vo.getOutRefundNo());
    }


}
